﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Windows.Forms;
using System.Xml.Serialization;
using SalaryReport.Core.Events;

namespace SalaryReport.Core.Excel
{
    [Serializable]
    public class ExcelSettings : INotify
    {
        private const string fileName = "settings.dat";

        private readonly XmlSerializer serializer;

        private List<ExcelItem> items;

        private Control container;

        private void Notify(SalaryArgs args)
        {
            if (OnNotify != null)
            {
                OnNotify(this, args);
            }
        }

        private void Default()
        {
            var userName = new ExcelColumn(true) { Name = "ФИО", Column = ExcelColumnName.A, TemplateName = "#name" };
            var userEmail = new ExcelColumn(true) { Name = "Почта", Column = ExcelColumnName.B, TemplateName = "#email" };

            Add(userName);
            Add(userEmail);
        }

        #region Public methods

        public ExcelSettings()
        {
            items = new List<ExcelItem>();
            serializer = new XmlSerializer(typeof(List<ExcelItem>));
        }

        public event EventHandler<SalaryArgs> OnNotify;

        public ReadOnlyCollection<ExcelItem> Items
        {
            get { return new ReadOnlyCollection<ExcelItem>(items); }
        }

        public void Add(ExcelItem item)
        {
            if (item == null)
            {
                Notify(new SalaryArgs("Add -> argument is NULL"));
            }
            else
            {
                item.btnRemove.Click += (sender, args) => Remove(item);
                items.Add(item);
                if (container != null)
                {
                    item.DisplayOnElement(container, items.Count - 1);
                }
            }
        }

        public void Remove(ExcelItem item)
        {
            if (item == null)
            {
                Notify(new SalaryArgs("Remove -> argument is NULL"));
            }
            else if (!items.Contains(item))
            {
                Notify(new SalaryArgs("Remove -> can't find item in the list"));
            }
            else
            {
                items.Remove(item);
            }
        }

        public void Save()
        {
            try
            {
                using (var stream = File.Create(fileName))
                {
                    serializer.Serialize(stream, items);
                }
            }
            catch (Exception ex)
            {
                Notify(new SalaryArgs(ex.Message + ((ex.InnerException == null) ? string.Empty : ex.InnerException.Message)));
            }
        }

        public void Load()
        {
            try
            {
                if (File.Exists(fileName))
                {
                    using (var stream = File.OpenRead(fileName))
                    {
                        items = (List<ExcelItem>) serializer.Deserialize(stream);
                        items.ForEach(item => item.btnRemove.Click += (sender, args) => Remove(item));
                        items.ForEach(item => item.btnRemove.Visible = !item.IsMandatory);
                    }
                }
                else
                {
                    Default();
                }
            }
            catch (Exception ex)
            {
                Notify(new SalaryArgs(ex.Message + ((ex.InnerException == null) ? string.Empty : ex.InnerException.Message)));
            }
        }

        public void DisplayOnElement(Control control)
        {
            container = control;
            for (var i = 0; i < items.Count; i++)
            {
                items[i].DisplayOnElement(control, i);
            }
        }

        #endregion
    }
}